/*
 * @Author: LVGRAPE
 * @Date: 2023-09-22 13:59:31
 * @LastEditTime: 2025-06-25 10:30:51
 * @LastEditors: LVGRAPE
 * @Description:
 * @FilePath: \ZINO_FC_V4\ZINO\hardware\si24r1\si24r1.c
 * 要啥没啥，爱咋咋的
 */
#include "si24r1.h"

#define DBG_SECTION_NAME  "2.4G"
#define DBG_LEVEL         DBG_LOG
#include <rtdbg.h>

#define SI24R1_WRITE_REG(dev, reg, val) dev->port.ops->write_reg(&dev->port, reg, (uint8_t*)&(dev->onchip_config.val), 1)
#define SI24R1_WRITE_REGs(dev, reg, val, len) dev->port.ops->write_reg(&dev->port, reg, (uint8_t*)(dev->onchip_config.val), len)
#define SI24R1_WRITE_RX_ADDR(dev, addr) dev->port.ops->write_reg(&dev->port, SI24R1_REG_RX_ADDR_P0, addr, 5)
#define SI24R1_WRITE_TX_ADDR(dev, addr) dev->port.ops->write_reg(&dev->port, SI24R1_REG_TX_ADDR, addr, 5)
uint8_t si24r1_read_reg_byte(struct si24r1* s, uint8_t reg)
{
    uint8_t val;
    s->port.ops->read_reg(&s->port, reg, &val, 1);
    return val;
}
uint8_t si24r1_write_reg_byte(struct si24r1* s, uint8_t reg, uint8_t val)
{
    return s->port.ops->write_reg(&s->port, reg, &val, 1);
}
uint8_t si24r1_write_command(struct si24r1* s, uint8_t cmd)
{
    return s->port.ops->write(&s->port, cmd, 0, 0);
}
/**
 * @brief 加载默认配置（未写入硬件，需要si24r1_update_onchip_config写入硬件）
 *
 * @param s
 */
void si24r1_fill_default_config(struct si24r1* s)
{
    rt_memset(&(s->onchip_config), 0, sizeof(si24r1_regs_t));

    /**all iqr on, pwr down, crc on with 1byte */
    s->onchip_config.config.EN_CRC = 1;
    s->onchip_config.config.CRCO = 1;
    /**enable pie0 ack*/
    s->onchip_config.en_aa.ENAA_P0 = 1;
    /**enable pie0 rx*/
    s->onchip_config.en_rxaddr.ERX_P0 = 1;
    /**diable auto transmit */
    s->onchip_config.setup_retr.ARC = 0;
    s->onchip_config.setup_retr.ARD = 0;
    /**7 dBm, 250kbps */
    s->onchip_config.rf_setup.RF_DR_LOW = 1;
    s->onchip_config.rf_setup.RF_PWR = 7;
    /**number of bytes in pie0 */
    s->onchip_config.rx_pw_p0.RX_PW_P0 = 19;

    /**rx addr */
    s->onchip_config.rx_addr_p0.addr[0] = 0x01;
    s->onchip_config.rx_addr_p0.addr[1] = 0x23;
    s->onchip_config.rx_addr_p0.addr[2] = 0x45;
    s->onchip_config.rx_addr_p0.addr[3] = 0x67;
    s->onchip_config.rx_addr_p0.addr[4] = 0x89;
    /**tx addr */
    s->onchip_config.tx_addr.addr[0] = 0x01;
    s->onchip_config.tx_addr.addr[1] = 0x23;
    s->onchip_config.tx_addr.addr[2] = 0x45;
    s->onchip_config.tx_addr.addr[3] = 0x67;
    s->onchip_config.tx_addr.addr[4] = 0x89;
    /**channel */
    s->onchip_config.rf_ch.RF_CH = 0;

}
/**
 * @brief 将寄存器配置写入硬件
 *
 * @param s
 */
void si24r1_update_onchip_config(struct si24r1* s)
{
    s->port.ops->reset_ce(&s->port);
    SI24R1_WRITE_REG(s, SI24R1_REG_CONFIG, config);
    SI24R1_WRITE_REG(s, SI24R1_REG_ENAA, en_aa);
    SI24R1_WRITE_REG(s, SI24R1_REG_EN_RXADDR, en_rxaddr);
    SI24R1_WRITE_REG(s, SI24R1_REG_SETUP_AW, setup_aw);
    SI24R1_WRITE_REG(s, SI24R1_REG_SETUP_RETR, setup_retr);
    SI24R1_WRITE_REG(s, SI24R1_REG_RF_CH, rf_ch);
    SI24R1_WRITE_REG(s, SI24R1_REG_RF_SETUP, rf_setup);
    SI24R1_WRITE_REG(s, SI24R1_REG_STATUS, status);//清除中断
    SI24R1_WRITE_REGs(s, SI24R1_REG_RX_ADDR_P0, rx_addr_p0.addr, 5);
    SI24R1_WRITE_REGs(s, SI24R1_REG_RX_ADDR_P1, rx_addr_p1.addr, 5);
    SI24R1_WRITE_REG(s, SI24R1_REG_RX_ADDR_P2, rx_addr_p2.addr);
    SI24R1_WRITE_REG(s, SI24R1_REG_RX_ADDR_P3, rx_addr_p3.addr);
    SI24R1_WRITE_REG(s, SI24R1_REG_RX_ADDR_P4, rx_addr_p4.addr);
    SI24R1_WRITE_REG(s, SI24R1_REG_RX_ADDR_P5, rx_addr_p5.addr);
    SI24R1_WRITE_REGs(s, SI24R1_REG_TX_ADDR, tx_addr.addr, 5);
    SI24R1_WRITE_REG(s, SI24R1_REG_RX_PW_P0, rx_pw_p0);
    SI24R1_WRITE_REG(s, SI24R1_REG_RX_PW_P1, rx_pw_p1);
    SI24R1_WRITE_REG(s, SI24R1_REG_RX_PW_P2, rx_pw_p2);
    SI24R1_WRITE_REG(s, SI24R1_REG_RX_PW_P3, rx_pw_p3);
    SI24R1_WRITE_REG(s, SI24R1_REG_RX_PW_P4, rx_pw_p4);
    SI24R1_WRITE_REG(s, SI24R1_REG_RX_PW_P5, rx_pw_p5);
    SI24R1_WRITE_REG(s, SI24R1_REG_DYNPD, dynpd);
    SI24R1_WRITE_REG(s, SI24R1_REG_FEATURE, feature);

    s->port.ops->write(&s->port, SI24R1_CMD_FLUSH_RX, 0,0);//NOTE 必须！！！否则收发失败！！！清空RX FIFO
    s->port.ops->write(&s->port, SI24R1_CMD_FLUSH_TX, 0,0);//NOTE 必须！！！否则收发失败！！！清空TX FIFO

    s->port.ops->set_ce(&s->port);
}
void si24r1_update_user_config(struct si24r1* s)
{
    //address
    s->port.ops->write_reg(&s->port, SI24R1_REG_RX_ADDR_P0, s->user_config.address, 5);
    s->onchip_config.rf_setup.RF_PWR = s->user_config.tx_power;//TX POWER
    if (s->user_config.band == SI24R1_BANDWITH_250K) //BANDWITH
    {
        s->onchip_config.rf_setup.RF_DR_LOW = 1;
        s->onchip_config.rf_setup.RF_DR_HIGH = 0;
    }
    else
    {
        s->onchip_config.rf_setup.RF_DR_LOW = 0;
        s->onchip_config.rf_setup.RF_DR_HIGH = s->user_config.band;
    }
    s->onchip_config.rf_ch.RF_CH = s->user_config.channel;//CHANNEL
    s->onchip_config.config.PRIM_RX = s->user_config.role;

    SI24R1_WRITE_REG(s, SI24R1_REG_CONFIG, config);
    SI24R1_WRITE_REG(s, SI24R1_REG_RF_CH, rf_ch);
    SI24R1_WRITE_REG(s, SI24R1_REG_RF_SETUP, rf_setup);
    SI24R1_WRITE_RX_ADDR(s, s->user_config.address);
    SI24R1_WRITE_RX_ADDR(s, s->user_config.address);
}
void si24r1_check_all_reg(struct si24r1* s)
{
    uint8_t rx[5];
#define REG_VAL(reg) si24r1_read_reg_byte(s,reg)
    LOG_D("SI24R1_REG_CONFIG:%02X ", REG_VAL(SI24R1_REG_CONFIG));
    LOG_D("SI24R1_REG_ENAA:%02X ", REG_VAL(SI24R1_REG_ENAA));
    LOG_D("SI24R1_REG_EN_RXADDR:%02X ", REG_VAL(SI24R1_REG_EN_RXADDR));
    LOG_D("SI24R1_REG_SETUP_AW:%02X ", REG_VAL(SI24R1_REG_SETUP_AW));
    LOG_D("SI24R1_REG_SETUP_RETR:%02X ", REG_VAL(SI24R1_REG_SETUP_RETR));
    LOG_D("SI24R1_REG_RF_CH:%02X ", REG_VAL(SI24R1_REG_RF_CH));
    LOG_D("SI24R1_REG_RF_SETUP:%02X ", REG_VAL(SI24R1_REG_RF_SETUP));
    LOG_D("SI24R1_REG_STATUS:%02X ", REG_VAL(SI24R1_REG_STATUS));
    LOG_D("SI24R1_REG_OBSERVE_TX:%02X ", REG_VAL(SI24R1_REG_OBSERVE_TX));
    LOG_D("SI24R1_REG_RSSI:%02X ", REG_VAL(SI24R1_REG_RSSI));
    s->port.ops->read_reg(&s->port, SI24R1_REG_RX_ADDR_P0, rx, 5);
    LOG_D("SI24R1_REG_RX_ADDR_P0:%02X-%02X-%02X-%02X-%02X", rx[0], rx[1], rx[2], rx[3], rx[4]);
    s->port.ops->read_reg(&s->port, SI24R1_REG_RX_ADDR_P1, rx, 5);
    LOG_D("SI24R1_REG_RX_ADDR_P1:%02X-%02X-%02X-%02X-%02X", rx[0], rx[1], rx[2], rx[3], rx[4]);
    LOG_D("SI24R1_REG_RX_ADDR_P2:%02X ", REG_VAL(SI24R1_REG_RX_ADDR_P2));
    LOG_D("SI24R1_REG_RX_ADDR_P3:%02X ", REG_VAL(SI24R1_REG_RX_ADDR_P3));
    LOG_D("SI24R1_REG_RX_ADDR_P4:%02X ", REG_VAL(SI24R1_REG_RX_ADDR_P4));
    LOG_D("SI24R1_REG_RX_ADDR_P5:%02X ", REG_VAL(SI24R1_REG_RX_ADDR_P5));
    s->port.ops->read_reg(&s->port, SI24R1_REG_TX_ADDR, rx, 5);
    LOG_D("SI24R1_REG_TX_ADDR:%02X-%02X-%02X-%02X-%02X", rx[0], rx[1], rx[2], rx[3], rx[4]);
    LOG_D("SI24R1_REG_RX_PW_P0:%02X ", REG_VAL(SI24R1_REG_RX_PW_P0));
    LOG_D("SI24R1_REG_RX_PW_P1:%02X ", REG_VAL(SI24R1_REG_RX_PW_P1));
    LOG_D("SI24R1_REG_RX_PW_P2:%02X ", REG_VAL(SI24R1_REG_RX_PW_P2));
    LOG_D("SI24R1_REG_RX_PW_P3:%02X ", REG_VAL(SI24R1_REG_RX_PW_P3));
    LOG_D("SI24R1_REG_RX_PW_P4:%02X ", REG_VAL(SI24R1_REG_RX_PW_P4));
    LOG_D("SI24R1_REG_RX_PW_P5:%02X ", REG_VAL(SI24R1_REG_RX_PW_P5));
    LOG_D("SI24R1_REG_FIFO_STATUS:%02X ", REG_VAL(SI24R1_REG_FIFO_STATUS));
    LOG_D("SI24R1_REG_DYNPD:%02X ", REG_VAL(SI24R1_REG_DYNPD));
    LOG_D("SI24R1_REG_FEATURE:%02X ", REG_VAL(SI24R1_REG_FEATURE));
}
int si24r1_send_data(struct si24r1* s, uint8_t* data, uint8_t len, uint8_t pipe)
{
    if (len > 32)
        return RT_ERROR;

    if (s->user_config.role == SI24R1_ROLE_TX)
    {
        s->port.ops->write(&s->port, SI24R1_CMD_W_TX_PAYLOAD, data, len);
    }
    else
    {
        pipe &= 0x07;
        s->port.ops->write(&s->port, SI24R1_CMD_W_ACK_PAYLOAD | pipe, data, len);
        rt_sem_release(s->send_sem);
    }
    return RT_EOK;
}
void __si24r1_irq_handler(void* param)
{
    struct si24r1* si = (struct si24r1*)param;
    rt_sem_release(si->sem);
}

rt_err_t si24r1_init(struct si24r1* s, char* spi_name, int ce_pin, int iqr_pin, struct si24r1_callback* cb)
{
    rt_err_t res = RT_EOK;
    RT_ASSERT(s != RT_NULL);
    RT_ASSERT(cb != RT_NULL);

    // s->cb = cb;
    // s->sem = rt_sem_create("si_irq", 0, RT_IPC_FLAG_FIFO);
    // s->send_sem = rt_sem_create("si_send", 0, RT_IPC_FLAG_FIFO);

    res = hal_si24r1_port_init(&s->port, spi_name, ce_pin, iqr_pin, __si24r1_irq_handler, s);
    if (res != RT_EOK)
    {
        LOG_E("hal_si24r1_port_init failed!");
        return res;
    }
    if (ce_pin != -1)
    {
        s->flags.using_irq = 1;
    }
    // s->cb = cb;
    // s->sem = rt_sem_create("si_irq", 0, RT_IPC_FLAG_FIFO);
    // s->send_sem = rt_sem_create("si_send", 0, RT_IPC_FLAG_FIFO);
    return res;
}

/**
 * @brief check status and inform
 * @param s :pointer of struct si24r1
 * @return -x:error   0:nothing   1:tx_done   2:rx_done   3:tx_rx_done
 */
int si24r1_run(struct si24r1* s)
{
    int rvl = 0;
    uint8_t pipe = 0;
    uint8_t status;
    if (s->flags.using_irq)
    {
        // LOG_D("waiting irq sem");
        rt_sem_take(s->sem, RT_WAITING_FOREVER);
    }

    s->port.ops->read_reg(&s->port, SI24R1_REG_STATUS, &status, 1);
    rt_memcpy(&s->onchip_config.status, &status, 1);
    pipe = s->onchip_config.status.RX_P_NO;

    // static uint8_t status_last = 0;
    // if (status_last != status)
    // {
    //     status_last = status;
        // LOG_D("status:0x%02X", status);
    // }

    if (s->user_config.role == SI24R1_ROLE_TX)
    {
        if (s->onchip_config.status.MAX_RT)
        {
            LOG_D("MAX_RT");
            s->port.ops->write_reg(&s->port, SI24R1_REG_STATUS, (uint8_t *)&s->onchip_config.status, 1);
            s->port.ops->write(&s->port, SI24R1_CMD_FLUSH_TX, 0, 0);
            if (s->cb->tx_done) s->cb->tx_done(s, 0);
            return -1;
        }
        if (s->onchip_config.status.RX_DR)
        {
            uint8_t data[32];
            uint8_t len = 0;
            // uint8_t len = read_top_rxfifo_width(nrf24);
            // read_rx_payload(nrf24, data, len);
            LOG_D("RX_DR");
            s->port.ops->read(&s->port, SI24R1_CMD_R_RX_PL_WID, &len, 1);
            s->port.ops->read(&s->port, SI24R1_CMD_R_RX_PAYLOAD, data, len);
            s->port.ops->write_reg(&s->port, SI24R1_REG_STATUS, (uint8_t *)&s->onchip_config.status, 1);
            if (s->cb->rx_ind) s->cb->rx_ind(s, data, len, 0);

            rvl |= 2;
        }
        if (s->onchip_config.status.TX_DS)
        {
            LOG_D("TX_DS");
            s->port.ops->write_reg(&s->port, SI24R1_REG_STATUS, (uint8_t *)&s->onchip_config.status, 1);
            if (s->cb->tx_done) s->cb->tx_done(s, 0);

            rvl |= 1;
        }
    }
    else
    {
        if (pipe <= 5 && s->onchip_config.status.RX_DR)
        {
            uint8_t data[32];
            uint8_t len = 0;
            // LOG_D("<-RX_DR");
            s->port.ops->read(&s->port, SI24R1_CMD_R_RX_PL_WID, &len, 1);
            s->port.ops->read(&s->port, SI24R1_CMD_R_RX_PAYLOAD, data, len);
            s->port.ops->write_reg(&s->port, SI24R1_REG_STATUS, (uint8_t *)&s->onchip_config.status, 1);
            s->port.ops->write(&s->port, SI24R1_CMD_FLUSH_RX, RT_NULL, 0);
            if (s->cb->rx_ind)
            {
                s->cb->rx_ind(s, data, len, pipe);
                rvl |= 2;
            }
            if (rt_sem_trytake(s->send_sem) == RT_EOK)
            {
                if (s->cb->tx_done) s->cb->tx_done(s, pipe);
                rvl |= 1;
            }
        }
    }

    return rvl;
}
